#include "sfx_win32_ds_dynlink.h"

sfx_ds_entrypoints_t sfx_ds = { 0, 0, 0, 0, 0, 0, 0 };

static HRESULT WINAPI DummyDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
    (void)rclsid; /* unused parameter */
    (void)riid; /* unused parameter */
    (void)ppv; /* unused parameter */
    return CLASS_E_CLASSNOTAVAILABLE;
}

static HRESULT WINAPI DummyDirectSoundCreate(LPGUID lpcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter)
{
    (void)lpcGuidDevice; /* unused parameter */
    (void)ppDS; /* unused parameter */
    (void)pUnkOuter; /* unused parameter */
    return E_NOTIMPL;
}

static HRESULT WINAPI DummyDirectSoundEnumerateW(LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext)
{
    (void)lpDSEnumCallback; /* unused parameter */
    (void)lpContext; /* unused parameter */
    return E_NOTIMPL;
}

static HRESULT WINAPI DummyDirectSoundEnumerateA(LPDSENUMCALLBACKA lpDSEnumCallback, LPVOID lpContext)
{
    (void)lpDSEnumCallback; /* unused parameter */
    (void)lpContext; /* unused parameter */
    return E_NOTIMPL;
}

static HRESULT WINAPI DummyDirectSoundCaptureCreate(LPGUID lpcGUID, LPDIRECTSOUNDCAPTURE *lplpDSC, LPUNKNOWN pUnkOuter)
{
    (void)lpcGUID; /* unused parameter */
    (void)lplpDSC; /* unused parameter */
    (void)pUnkOuter; /* unused parameter */
    return E_NOTIMPL;
}

static HRESULT WINAPI DummyDirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW lpDSCEnumCallback, LPVOID lpContext)
{
    (void)lpDSCEnumCallback; /* unused parameter */
    (void)lpContext; /* unused parameter */
    return E_NOTIMPL;
}

static HRESULT WINAPI DummyDirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA lpDSCEnumCallback, LPVOID lpContext)
{
    (void)lpDSCEnumCallback; /* unused parameter */
    (void)lpContext; /* unused parameter */
    return E_NOTIMPL;
}


void sfx_ds_init_ds_entrypoints(void)
{
    sfx_ds.hInstance_ = LoadLibrary("dsound.dll");
    if( sfx_ds.hInstance_ != NULL )
    {
        sfx_ds.DllGetClassObject =
                (HRESULT (WINAPI *)(REFCLSID, REFIID , LPVOID *))
                GetProcAddress( sfx_ds.hInstance_, "DllGetClassObject" );
        if( sfx_ds.DllGetClassObject == NULL )
            sfx_ds.DllGetClassObject = DummyDllGetClassObject;

        sfx_ds.DirectSoundCreate =
                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN))
                GetProcAddress( sfx_ds.hInstance_, "DirectSoundCreate" );
        if( sfx_ds.DirectSoundCreate == NULL )
            sfx_ds.DirectSoundCreate = DummyDirectSoundCreate;

        sfx_ds.DirectSoundEnumerateW =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
                GetProcAddress( sfx_ds.hInstance_, "DirectSoundEnumerateW" );
        if( sfx_ds.DirectSoundEnumerateW == NULL )
            sfx_ds.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;

        sfx_ds.DirectSoundEnumerateA =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
                GetProcAddress( sfx_ds.hInstance_, "DirectSoundEnumerateA" );
        if( sfx_ds.DirectSoundEnumerateA == NULL )
            sfx_ds.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;

        sfx_ds.DirectSoundCaptureCreate =
                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN))
                GetProcAddress( sfx_ds.hInstance_, "DirectSoundCaptureCreate" );
        if( sfx_ds.DirectSoundCaptureCreate == NULL )
            sfx_ds.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;

        sfx_ds.DirectSoundCaptureEnumerateW =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
                GetProcAddress( sfx_ds.hInstance_, "DirectSoundCaptureEnumerateW" );
        if( sfx_ds.DirectSoundCaptureEnumerateW == NULL )
            sfx_ds.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;

        sfx_ds.DirectSoundCaptureEnumerateA =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
                GetProcAddress( sfx_ds.hInstance_, "DirectSoundCaptureEnumerateA" );
        if( sfx_ds.DirectSoundCaptureEnumerateA == NULL )
            sfx_ds.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
    }
    else
    {
        /* initialize with dummy entry points to make live easy when ds isn't present */
        sfx_ds.DirectSoundCreate = DummyDirectSoundCreate;
        sfx_ds.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
        sfx_ds.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
        sfx_ds.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
        sfx_ds.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
        sfx_ds.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
    }
}


void sfx_ds_deinit_ds_entrypoints(void)
{
    if( sfx_ds.hInstance_ != NULL )
    {
        /* ensure that we crash reliably if the entry points arent initialised */
        sfx_ds.DirectSoundCreate = 0;
        sfx_ds.DirectSoundEnumerateW = 0;
        sfx_ds.DirectSoundEnumerateA = 0;
        sfx_ds.DirectSoundCaptureCreate = 0;
        sfx_ds.DirectSoundCaptureEnumerateW = 0;
        sfx_ds.DirectSoundCaptureEnumerateA = 0;

        FreeLibrary( sfx_ds.hInstance_ );
        sfx_ds.hInstance_ = NULL;
    }
}